from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
import os

from html import CheckBox, DropDown, MultiSelect #importing the html wrappers
from tables import InstructorPref, Instructor, Section, AppState, Ta, WantedTaInstructorPref, UnwantedTaInstructorPref
from google.appengine.ext import db
import staticInits
import validate #import validation
import cgi #for escaping html chars in forms


class InstructorPrefs(webapp.RequestHandler):
    '''Class that allows an instructor to request TAs'''
    #instructor = ["Qwerty Asdf"]
    #instructors = {}
    #courses = ["cs315", "cs371p", "cs373"] #get from database later
    #students = {}
    #specialties = ["Software Engineering", "Artificial Intelligence", "Law"]
    #wanted = MultiSelect(students,(),"wanted")
    #unwanted = MultiSelect(students,(),"unwanted")
    native = None
    specialization = None
    #data format "key":((wanted),(unwanted),native,specialization)
    #data = {
    #    "cs315":(("alice","eve"),("bob"),False,"Law"),
    #    "cs371p":(("alice"),("eve"),True,"Artificial Intelligence"),
    #    "cs373":(("bob","eve"),("alice"),True,"Software Engineering")
    #    }
    def __init__(self):
        webapp.RequestHandler.__init__(self)
        



        self.currentState = AppState.get_by_key_name('currentState')
        self.currentSemester = self.currentState.semester

        self.instructor = None
        self.instructors = {}
        self.students = {}
        self.sections = {}
        self.section2 = {}
        self.data = {}
        self.spec = {}
        self.byEid = {}
        for row in db.GqlQuery("SELECT * FROM Instructor"):
            self.instructors["" + row.lastName + ", " + row.firstName] = row
        for row in db.GqlQuery("SELECT * FROM Ta WHERE semester = :semester AND submitted = :submitted", semester = self.currentSemester, submitted = True):
            if not row.submitted:
                continue
            self.students["" + row.lastName + ", " + row.firstName] = row
        for row in db.GqlQuery("SELECT * FROM Section WHERE semester = :1", self.currentSemester):
            self.sections[row.uniqueNumber] = row
        for row in db.GqlQuery("SELECT * FROM Specialization"):
            self.spec[row.name] = row
        for row in db.GqlQuery("SELECT * FROM Section WHERE semester = :1", self.currentSemester):
            self.section2[str(row.uniqueNumber) + " - " + row.course.identifier + " - " + row.course.name] = row
        for row in db.GqlQuery("SELECT * FROM InstructorPref"):
            #print row.section.semester == self.currentSemester
            if str(row.section.semester) == str(self.currentSemester):
                self.data[row.section.uniqueNumber] = row
        for row in db.GqlQuery("SELECT * FROM Instructor"):
            assert row.eid not in self.instructors.keys()
            self.byEid[row.eid] = row

        self.wanted = MultiSelect(self.students,(),"wanted")
        self.unwanted = MultiSelect(self.students,(),"unwanted")
    
    def get(self):
        self.redirect('/login')
        """if self.currentState.time.name != 'Instructor Apply':
            self.response.out.write(staticInits.notTimeStr(verb = 'applying'))
        else:
            
            
            '''
            Updates form when user navigates to page.
            '''
            self.renderTemplate()"""
        
    def post(self):
        if self.currentState.time.name != 'Instructor Apply':
            self.response.out.write(staticInits.notTimeStr(verb = 'applying'))
            return
        eid = self.request.get('eid', default_value="default").lower()
        if eid in self.byEid:
            #self.response.out.write('eid: '+eid+'<br>')
            instructor = "" + self.byEid[eid].lastName + ", " + self.byEid[eid].firstName
        elif eid != "default":
            self.response.out.write('You are not logged in as an instructor.')
            self.renderTemplate()
            return
        else:
            instructor = self.request.get('instructorList')
            #self.response.out.write(instructor)
            #print instructor
        changed = False
        '''        Updates form when user changes course dropdown or hits submit.        '''        #eventually link in a database        #self.response.out.write(str(self.request.arguments()))
        

        if instructor not in self.instructors:
            #print instructor
            self.renderTemplate()
            return
        course = self.request.get("courseList", default_value=None)
        unique = None if course not in self.section2 else self.section2[course].uniqueNumber
        #print self.sections[unique].instructor.lastName
        #self.response.out.write(str(self.sections[unique].instructor.lastName) + ' ' + instructor)
        #if course is not None: print 'booo'
        if unique is not None and self.sections[unique].instructor.lastName + ', ' +  self.sections[unique].instructor.firstName != str(instructor):
            self.renderTemplate(instructor)
            return
        button = self.request.get("button", default_value=None)

        if course in self.section2 and self.section2[course].uniqueNumber not in self.data:
            self.data[unique] = InstructorPref(section = self.sections[unique], nativeEnglish = False)
            self.data[unique].put()
        if button != None:
            if not validate.validateNoIntersection(set(self.request.get_all("wanted")),set(self.request.get_all("unwanted"))):
                self.response.out.write('<font color="red">A student appears in both Wanted and Unwanted lists.</font><br />')
                self.wanted = MultiSelect(self.students,self.request.get_all("wanted"),"wanted")
                self.unwanted = MultiSelect(self.students,self.request.get_all("unwanted"),"unwanted")
                self.native = CheckBox(self.request.get("native"),"native")
                self.specialization = DropDown(self.spec,self.request.get("specialization"),"specialization")
                self.renderTemplate(instructor, course)
                return
            else:
                temp = self.request.get_all("wanted")
                #print temp
                wanted = []
                unwanted = []
                wants = {}
                nowants = {}
                for row in db.GqlQuery("SELECT * FROM WantedTaInstructorPref WHERE instructorPref = :x", x = self.data[unique]):
                    wants[row.ta.lastName + ', ' + row.ta.firstName] = row
                for row in db.GqlQuery("SELECT * FROM UnwantedTaInstructorPref WHERE instructorPref = :x", x = self.data[unique]):
                    nowants[row.ta.lastName + ', ' + row.ta.firstName] = row
                #print len(wants), len(nowants)
                for row in self.students:
                    if row in temp:
                        if row not in wants:
                            #print row + 'not in wants'
                            wants[row] = WantedTaInstructorPref(instructorPref = self.data[unique], ta = self.students[row])
                            wants[row].put()
                        wanted.append(row)
                    if row in wants:
                        if row not in temp:
                            wants[row].delete()
                            del wants[row]
                #print len(wants)
                #self.wanted = MultiSelect(self.students,[x.lastName + ", " + x.firstName for x in wanted],"wanted")
                temp = self.request.get_all("unwanted")
                for row in self.students:
                    if row in temp:
                        if row not in nowants:
                            nowants[row] = UnwantedTaInstructorPref(instructorPref = self.data[unique], ta = self.students[row])
                            nowants[row].put()
                        unwanted.append(row)
                    if row in nowants:
                        if row not in temp:
                            nowants[row].delete()
                            del nowants[row]
                #self.unwanted = MultiSelect(self.students,[x.lastName + ", " + x.firstName for x in unwanted],"unwanted")
                #print self.request.get("native")
                self.data[unique].nativeEnglish = (self.request.get("native") == "on")
                if self.request.get("specialization") in self.spec:
                    self.data[unique].specialization = self.spec[self.request.get("specialization")]
                self.data[unique].put()
                changed = True
                #print self.data[unique].section.uniqueNumber, self.data[unique].nativeEnglish, self.data[unique].specialization
        if course not in self.section2:
            course = None
        self.renderTemplate(instructor, course,changed)
        
    def renderTemplate(self, instructor = None, course = None, changed = False):
        semester = self.currentState.semester
        unique = None
        if course != None:
            unique = self.section2[course].uniqueNumber
        '''Renders the instructor form'''
        #print course, instructor
        if instructor == None:
            self.instructorList = DropDown(self.instructors,"","instructorList",True)
            self.courseList = None
            showCourse = False
            showInstructor = False
        else:
	    myCourses = [(str(row.uniqueNumber) + " - " + row.course.identifier + " - " + row.course.name) for row in self.sections.values() if (row.instructor.firstName == self.instructors[instructor].firstName and row.instructor.lastName == self.instructors[instructor].lastName)]
            #print [x.instructor.firstName == self.instructors[instructor].firstName and x.instructor.lastName == self.instructors[instructor].lastName for x in self.sections.values()]
            #print self.data
            showInstructor = True
            self.instructorList = instructor#DropDown(self.instructors,instructor,"instructorList",True)
            if course == None:
                self.courseList = DropDown(myCourses,"","courseList",True)
                showCourse = False
            else:
                #if changed:
                    #print self.data[unique].section.uniqueNumber, self.data[unique].nativeEnglish, self.data[unique].specialization
                    #self.data[unique].put()
                #for s in self.data[unique].wantedTaInstructorPrefs:
                #    print s.ta
                self.courseList = DropDown(myCourses, course,"courseList",True)
                showCourse = True
                #data = db.GqlQuery("SELECT * FROM InstructorPref WHERE section = :t", t = self.section2[str(course)]).get()
                #for row in data:
                #    print row.delete()
                #if changed:
                #    print data.section.uniqueNumber, data.nativeEnglish, data.specialization
                wanted = []
                unwanted = []
                for row in self.data[unique].wantedTaInstructorPrefs:
                    #print 'Caw!!'
                    wanted.append(row.ta.lastName + ", " + row.ta.firstName)
                #if wanted != []: print wanted
                self.wanted = MultiSelect(self.students,wanted,"wanted")
                for row in self.data[unique].unwantedTaInstructorPrefs:
                    unwanted.append(row.ta.lastName + ", " + row.ta.firstName)
                self.unwanted = MultiSelect(self.students,unwanted,"unwanted")
                self.native = CheckBox(self.data[unique].nativeEnglish,"native")
                if self.data[unique].specialization != None:
                    temp = self.data[unique].specialization.name
                else:
                    temp = None
                self.specialization = DropDown(self.spec, temp, "specialization")
        templateValues = {
            'semester': semester,
            'showCourse': showCourse,
            'showInstructor': showInstructor,
            'instructorList': self.instructorList,
            'courseList': self.courseList,
            'wanted': self.wanted,
            'unwanted': self.unwanted,
            'native': self.native,
            'specialization': self.specialization}
        path = os.path.join(os.path.dirname(__file__), 'instructor.html')
        self.response.out.write(template.render(path, templateValues))
        
application = webapp.WSGIApplication([('/instructor', InstructorPrefs)], debug=True)
def main():
    run_wsgi_app(application)
if __name__ == "__main__":
    main()
